# HUB 插件 - 进度条模块
# 实现进度条对话框功能，提供界面友好的进度显示

require 'sketchup.rb'
require 'json'
require 'tempfile'
require 'fileutils'

module HUB
  module JDT
    # 使用file_loaded?机制防止重复加载
    unless file_loaded?(__FILE__)
      # 跟踪活跃的对话框
      @active_dialogs = {}
      
      # 添加进程ID（用于区分不同SketchUp实例）
      @process_id = Process.pid rescue "unknown_pid"
      
      # 进度文件存储目录
      @progress_dir = nil
      
      # 日志记录函数
      def self.log(message, level = 2)
        prefix = case level
          when 1 then "[DEBUG]"
          when 2 then "[INFO]"
          when 3 then "[ERROR]"
          else "[LOG]"
        end
        
        puts "#{prefix} #{Time.now.strftime('%Y-%m-%d %H:%M:%S')} - JDT[#{@process_id}]: #{message}"
      end
      
      # 标记此文件已加载
      file_loaded(__FILE__)
    end
    
    # 获取进度文件存储目录
    def self.get_progress_dir
      return @progress_dir if @progress_dir && File.directory?(@progress_dir)
      
      begin
        # 使用系统临时目录下的子目录
        temp_base = Dir.tmpdir
        progress_dir = File.join(temp_base, "hub_progress_#{@process_id}")
        
        # 确保目录存在
        FileUtils.mkdir_p(progress_dir) unless File.directory?(progress_dir)
        
        # 创建.keep文件标记目录
        keep_file = File.join(progress_dir, ".keep")
        File.write(keep_file, Time.now.to_s) unless File.exist?(keep_file)
        
        @progress_dir = progress_dir
        log("进度文件目录: #{progress_dir}")
        return progress_dir
      rescue => e
        log("创建进度文件目录失败: #{e.message}", 3)
        # 使用备用目录
        @progress_dir = Dir.tmpdir
        return Dir.tmpdir
      end
    end
    
    # 清理过期的进度文件
    def self.cleanup_progress_files
      begin
        progress_dir = get_progress_dir
        
        # 查找所有json文件
        pattern = File.join(progress_dir, "*.json")
        progress_files = Dir.glob(pattern)
        
        now = Time.now
        count = 0
        
        progress_files.each do |file|
          # 检查文件修改时间
          mtime = File.mtime(file)
          
          # 删除30分钟以上未修改的文件
          if now - mtime > 1800
            File.delete(file)
            count += 1
          end
        end
        
        log("已清理 #{count} 个过期进度文件") if count > 0
      rescue => e
        log("清理进度文件时出错: #{e.message}", 3)
      end
    end
    
    # 创建进度文件并初始化状态
    # @param progress_id [String] 进度标识
    # @param is_upload [Boolean] 是否为上传进度
    # @param filename [String] 处理的文件名
    # @return [String] 进度文件路径
    def self.create_progress_file(progress_id, is_upload, filename)
      begin
        progress_dir = get_progress_dir
        progress_file = File.join(progress_dir, "#{progress_id}.json")
        
        # 初始化进度数据
        progress_data = {
          id: progress_id,
          process_id: @process_id,
          is_upload: is_upload,
          filename: filename,
          status: is_upload ? "正在准备上传..." : "正在准备下载...",
          progress: 0,
          file_info: "准备#{is_upload ? '上传' : '下载'}文件: #{filename}",
          completed: false,
          last_update: Time.now.to_i,
          created_at: Time.now.to_i
        }
        
        # 写入进度文件
        File.open(progress_file, "w") do |f|
          f.write(JSON.generate(progress_data))
        end
        
        log("创建进度文件: #{progress_file}")
        return progress_file
      rescue => e
        log("创建进度文件失败: #{e.message}", 3)
        return nil
      end
    end
    
    # 更新进度文件
    # @param progress_id [String] 进度标识
    # @param updates [Hash] 要更新的字段
    # @return [Boolean] 是否更新成功
    def self.update_progress_file(progress_id, updates)
      begin
        progress_dir = get_progress_dir
        progress_file = File.join(progress_dir, "#{progress_id}.json")
        
        # 检查文件是否存在
        unless File.exist?(progress_file)
          log("进度文件不存在: #{progress_file}", 3)
          return false
        end
        
        # 为防止过于频繁的IO操作，检查上次更新时间
        last_updated = false
        
        # 获取文件修改时间
        file_mtime = File.mtime(progress_file).to_f
        
        # 当前时间
        current_time = Time.now.to_f
        
        # 只有当文件修改时间超过100毫秒前，或进度超过5%，或状态改变时才更新文件
        # 这样可以减少过于频繁的IO操作
        progress_change = updates[:progress]
        significant_update = false
        
        begin
          # 读取当前进度数据
          current_data = JSON.parse(File.read(progress_file), symbolize_names: true)
          
          # 检查是否有重大变化需要立即更新
          if progress_change && (progress_change - current_data[:progress]).abs >= 2
            significant_update = true
          end
          
          # 检查状态是否改变
          if updates[:status] && updates[:status] != current_data[:status]
            significant_update = true
          end
          
          # 检查是否标记为完成
          if updates[:completed] && !current_data[:completed]
            significant_update = true
          end
        rescue => e
          # 如果读取失败，直接更新
          significant_update = true
          log("读取当前进度数据失败，将直接更新文件: #{e.message}", 1)
        end
        
        # 如果距离上次修改超过100毫秒或有重大变化，则更新文件
        if (current_time - file_mtime) * 1000 > 100 || significant_update
          # 读取当前进度数据
          current_data = JSON.parse(File.read(progress_file), symbolize_names: true)
          
          # 更新数据
          updates.each do |key, value|
            current_data[key] = value
          end
          
          # 添加更新时间
          current_data[:last_update] = Time.now.to_i
          
          # 写入更新后的数据
          File.open(progress_file, "w") do |f|
            f.write(JSON.generate(current_data))
          end
          
          log("更新进度文件: #{progress_id}, 进度: #{current_data[:progress]}%, 状态: #{current_data[:status]}")
          return true
        else
          # 跳过此次更新，避免过于频繁的IO操作
          log("跳过频繁更新: #{progress_id}, 间隔过短", 1)
          return true # 返回true因为这不是错误
        end
      rescue => e
        log("更新进度文件失败: #{e.message}", 3)
        return false
      end
    end
    
    # 删除进度文件
    # @param progress_id [String] 进度标识
    def self.delete_progress_file(progress_id)
      begin
        progress_dir = get_progress_dir
        progress_file = File.join(progress_dir, "#{progress_id}.json")
        
        # 检查文件是否存在
        if File.exist?(progress_file)
          File.delete(progress_file)
          log("删除进度文件: #{progress_file}")
        end
      rescue => e
        log("删除进度文件失败: #{e.message}", 3)
      end
    end
    
    # 简化的下载进度条HTML模板 - 使用文件存储进度信息
    def self.get_download_html_template(filename, progress_id, progress_file)
      # 计算进度文件的绝对URL（用于JavaScript访问）
      progress_file_url = "file:///" + progress_file.gsub('\\', '/')
      
      <<~HTML
        <!DOCTYPE html>
        <html>
        <head>
          <meta charset="UTF-8">
          <title>HUB文件下载</title>
          <style>
            body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background-color: #f5f5f5; }
            .container { background-color: white; border-radius: 5px; padding: 15px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
            h3 { margin-top: 0; color: #333; }
            .status { margin: 15px 0; padding: 10px; background-color: #f0f7ff; border-left: 4px solid #0066cc; color: #333; }
            .progress-container { width: 100%; height: 20px; background-color: #eee; border-radius: 10px; margin: 15px 0; }
            .progress-bar { height: 100%; background-color: #4CAF50; border-radius: 10px; width: 0%; transition: width 0.3s; }
            .file-info { margin-top: 10px; font-size: 0.9em; color: #666; }
            #debug-info { display: none; font-size: 10px; color: #999; margin-top: 10px; }
          </style>
        </head>
        <body>
          <div class="container">
            <h3>HUB文件下载</h3>
            <div class="status" id="status">正在准备下载...</div>
            <div class="progress-container">
              <div class="progress-bar" id="progress-bar"></div>
            </div>
            <div class="file-info" id="file-info">准备下载文件: #{escape_html(filename.to_s)}</div>
            <div id="debug-info">进度ID: #{progress_id}, 进程ID: #{@process_id}</div>
          </div>

          <script>
            // 进度文件信息
            var progressId = "#{progress_id}";
            var progressFileUrl = "#{progress_file_url}";
            var processId = "#{@process_id}";
            var lastProgressValue = 0;
            var isCompleted = false;
            var updateCount = 0;
            var lastUpdateTime = Date.now();
            var errorCount = 0;
            var smoothProgress = 0; // 用于平滑显示的进度值
            var targetProgress = 0; // 实际目标进度
            var animationFrame = null; // 动画帧引用
            
            // 平滑更新进度条
            function updateProgressBarSmooth() {
              if (smoothProgress < targetProgress) {
                // 逐渐接近目标值，但速度随差距变化
                var diff = targetProgress - smoothProgress;
                var step = Math.max(0.1, diff * 0.1); // 至少移动0.1%，最多移动差距的10%
                smoothProgress += step;
                
                // 更新DOM
                document.getElementById('progress-bar').style.width = smoothProgress + '%';
                
                // 继续动画
                animationFrame = requestAnimationFrame(updateProgressBarSmooth);
              }
            }
            
            // 设置目标进度并开始平滑动画
            function setTargetProgress(newTarget) {
              if (newTarget > targetProgress) { // 只有增加时才更新
                targetProgress = newTarget;
                
                // 如果没有动画正在进行，启动一个
                if (!animationFrame) {
                  animationFrame = requestAnimationFrame(updateProgressBarSmooth);
                }
              }
            }
            
            // 使用fetch API获取进度数据
            function fetchProgressData() {
              // 添加随机参数防止缓存
              var url = progressFileUrl + "?t=" + Date.now();
              
              fetch(url)
                .then(response => {
                  if (!response.ok) {
                    throw new Error('获取进度数据失败: ' + response.status);
                  }
                  return response.text();
                })
                .then(text => {
                  try {
                    // 解析JSON数据
                    var data = JSON.parse(text);
                    updateProgressUI(data);
                    errorCount = 0; // 重置错误计数
                  } catch (e) {
                    console.error('解析进度数据失败:', e);
                    errorCount++;
                    
                    // 如果连续5次出错，显示调试信息
                    if (errorCount > 5) {
                      document.getElementById('debug-info').style.display = 'block';
                      document.getElementById('debug-info').innerHTML += '<br>解析错误: ' + e.message;
                    }
                  }
                })
                .catch(error => {
                  console.error('获取进度数据时出错:', error);
                  errorCount++;
                  
                  // 如果连续10次出错，显示调试信息
                  if (errorCount > 10) {
                    document.getElementById('debug-info').style.display = 'block';
                    document.getElementById('debug-info').innerHTML += '<br>获取错误: ' + error.message;
                  }
                });
            }
            
            // 更新UI
            function updateProgressUI(data) {
              // 检查数据有效性
              if (!data || typeof data !== 'object') return;
              
              // 更新上次更新时间
              lastUpdateTime = Date.now();
              updateCount++;
              
              // 更新状态文本（如果有变化）
              if (data.status) {
                document.getElementById('status').innerText = data.status;
              }
              
              // 更新进度条（如果有变化）
              if (typeof data.progress === 'number' && data.progress !== lastProgressValue) {
                lastProgressValue = data.progress;
                
                // 使用平滑动画更新进度条
                setTargetProgress(data.progress);
              }
              
              // 更新文件信息（如果有变化）
              if (data.file_info) {
                document.getElementById('file-info').innerText = data.file_info;
              }
              
              // 检查是否完成
              if (data.completed && !isCompleted) {
                isCompleted = true;
                document.getElementById('status').innerText = '下载已完成！准备导入...';
                setTargetProgress(100); // 直接设置为100%
              }
              
              // 如果出现问题（长时间无进度更新），显示调试信息
              if (updateCount > 10 && lastProgressValue < 10) {
                document.getElementById('debug-info').style.display = 'block';
              }
            }
            
            // 设置定时更新
            function startProgressUpdates() {
              // 立即获取一次进度
              fetchProgressData();
              
              // 定期获取进度更新（每200毫秒一次，比之前的300毫秒更频繁）
              setInterval(fetchProgressData, 200);
              
              // 设置检查更新超时的定时器
              setInterval(function() {
                var now = Date.now();
                // 如果5秒钟没有更新且未完成，显示警告
                if (!isCompleted && (now - lastUpdateTime) > 5000) {
                  document.getElementById('debug-info').style.display = 'block';
                  document.getElementById('debug-info').innerHTML += '<br>警告: 更新超时 (' + Math.round((now - lastUpdateTime)/1000) + 's)';
                }
              }, 1000);
            }
            
            // 启动进度更新
            startProgressUpdates();
          </script>
        </body>
        </html>
      HTML
    end
    
    # 简化的上传进度条HTML模板 - 使用文件存储进度信息
    def self.get_upload_html_template(filename, progress_id, progress_file)
      # 计算进度文件的绝对URL（用于JavaScript访问）
      progress_file_url = "file:///" + progress_file.gsub('\\', '/')
      
      <<~HTML
        <!DOCTYPE html>
        <html>
        <head>
          <meta charset="UTF-8">
          <title>HUB文件上传</title>
          <style>
            body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background-color: #f5f5f5; }
            .container { background-color: white; border-radius: 5px; padding: 15px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
            h3 { margin-top: 0; color: #333; }
            .status { margin: 15px 0; padding: 10px; background-color: #f0f7ff; border-left: 4px solid #0066cc; color: #333; }
            .progress-container { width: 100%; height: 20px; background-color: #eee; border-radius: 10px; margin: 15px 0; }
            .progress-bar { height: 100%; background-color: #4CAF50; border-radius: 10px; width: 0%; transition: width 0.3s; }
            .file-info { margin-top: 10px; font-size: 0.9em; color: #666; }
            #debug-info { display: none; font-size: 10px; color: #999; margin-top: 10px; }
          </style>
        </head>
        <body>
          <div class="container">
            <h3>HUB文件上传</h3>
            <div class="status" id="status">正在准备上传...</div>
            <div class="progress-container">
              <div class="progress-bar" id="progress-bar"></div>
            </div>
            <div class="file-info" id="file-info">准备上传文件: #{escape_html(filename.to_s)}</div>
            <div id="debug-info">进度ID: #{progress_id}, 进程ID: #{@process_id}</div>
          </div>

          <script>
            // 进度文件信息
            var progressId = "#{progress_id}";
            var progressFileUrl = "#{progress_file_url}";
            var processId = "#{@process_id}";
            var lastProgressValue = 0;
            var isCompleted = false;
            var updateCount = 0;
            var lastUpdateTime = Date.now();
            var errorCount = 0;
            var smoothProgress = 0; // 用于平滑显示的进度值
            var targetProgress = 0; // 实际目标进度
            var animationFrame = null; // 动画帧引用
            
            // 平滑更新进度条
            function updateProgressBarSmooth() {
              if (smoothProgress < targetProgress) {
                // 逐渐接近目标值，但速度随差距变化
                var diff = targetProgress - smoothProgress;
                var step = Math.max(0.1, diff * 0.1); // 至少移动0.1%，最多移动差距的10%
                smoothProgress += step;
                
                // 更新DOM
                document.getElementById('progress-bar').style.width = smoothProgress + '%';
                
                // 继续动画
                animationFrame = requestAnimationFrame(updateProgressBarSmooth);
              }
            }
            
            // 设置目标进度并开始平滑动画
            function setTargetProgress(newTarget) {
              if (newTarget > targetProgress) { // 只有增加时才更新
                targetProgress = newTarget;
                
                // 如果没有动画正在进行，启动一个
                if (!animationFrame) {
                  animationFrame = requestAnimationFrame(updateProgressBarSmooth);
                }
              }
            }
            
            // 使用fetch API获取进度数据
            function fetchProgressData() {
              // 添加随机参数防止缓存
              var url = progressFileUrl + "?t=" + Date.now();
              
              fetch(url)
                .then(response => {
                  if (!response.ok) {
                    throw new Error('获取进度数据失败: ' + response.status);
                  }
                  return response.text();
                })
                .then(text => {
                  try {
                    // 解析JSON数据
                    var data = JSON.parse(text);
                    updateProgressUI(data);
                    errorCount = 0; // 重置错误计数
                  } catch (e) {
                    console.error('解析进度数据失败:', e);
                    errorCount++;
                    
                    // 如果连续5次出错，显示调试信息
                    if (errorCount > 5) {
                      document.getElementById('debug-info').style.display = 'block';
                      document.getElementById('debug-info').innerHTML += '<br>解析错误: ' + e.message;
                    }
                  }
                })
                .catch(error => {
                  console.error('获取进度数据时出错:', error);
                  errorCount++;
                  
                  // 如果连续10次出错，显示调试信息
                  if (errorCount > 10) {
                    document.getElementById('debug-info').style.display = 'block';
                    document.getElementById('debug-info').innerHTML += '<br>获取错误: ' + error.message;
                  }
                });
            }
            
            // 更新UI
            function updateProgressUI(data) {
              // 检查数据有效性
              if (!data || typeof data !== 'object') return;
              
              // 更新上次更新时间
              lastUpdateTime = Date.now();
              updateCount++;
              
              // 更新状态文本（如果有变化）
              if (data.status) {
                document.getElementById('status').innerText = data.status;
              }
              
              // 更新进度条（如果有变化）
              if (typeof data.progress === 'number' && data.progress !== lastProgressValue) {
                lastProgressValue = data.progress;
                
                // 使用平滑动画更新进度条
                setTargetProgress(data.progress);
              }
              
              // 更新文件信息（如果有变化）
              if (data.file_info) {
                document.getElementById('file-info').innerText = data.file_info;
              }
              
              // 检查是否完成
              if (data.completed && !isCompleted) {
                isCompleted = true;
                document.getElementById('status').innerText = '上传已完成！准备生成提取码...';
                setTargetProgress(100); // 直接设置为100%
              }
              
              // 如果出现问题（长时间无进度更新），显示调试信息
              if (updateCount > 10 && lastProgressValue < 10) {
                document.getElementById('debug-info').style.display = 'block';
              }
            }
            
            // 设置定时更新
            function startProgressUpdates() {
              // 立即获取一次进度
              fetchProgressData();
              
              // 定期获取进度更新（每200毫秒一次，比之前的300毫秒更频繁）
              setInterval(fetchProgressData, 200);
              
              // 设置检查更新超时的定时器
              setInterval(function() {
                var now = Date.now();
                // 如果5秒钟没有更新且未完成，显示警告
                if (!isCompleted && (now - lastUpdateTime) > 5000) {
                  document.getElementById('debug-info').style.display = 'block';
                  document.getElementById('debug-info').innerHTML += '<br>警告: 更新超时 (' + Math.round((now - lastUpdateTime)/1000) + 's)';
                }
              }, 1000);
            }
            
            // 启动进度更新
            startProgressUpdates();
          </script>
        </body>
        </html>
      HTML
    end
    
    # 生成真正唯一的标识符 (包含进程ID，确保多实例环境下唯一)
    def self.generate_unique_id
      # 使用时间戳、随机数和进程ID生成唯一ID
      "#{@process_id}_#{Time.now.to_i}_#{rand(100000)}"
    end
    
    # 获取SketchUp窗口位置并计算对话框居中位置
    # @return [Hash] 包含left和top键的哈希表
    def self.calculate_dialog_position(dialog_width = 550, dialog_height = 250)
      begin
        # 默认位置（居中屏幕）
        screen_width = 1920  # 假设默认屏幕宽度
        screen_height = 1080 # 假设默认屏幕高度
        
        left = (screen_width - dialog_width) / 2
        top = (screen_height - dialog_height) / 2
        
        # 尝试获取SketchUp窗口位置
        begin
          # 检查是否可以访问SketchUp窗口
          if Sketchup.active_model && Sketchup.active_model.active_view
            # 获取活动视图
            view = Sketchup.active_model.active_view
            
            # 尝试获取视图的屏幕位置
            if view.respond_to?(:screen_coordinates)
              # 获取SketchUp视图的屏幕坐标
              point = [view.vpwidth / 2, view.vpheight / 2]
              screen_point = view.screen_coordinates(point)
              
              # 计算SketchUp窗口的中心
              su_center_x = screen_point.x
              su_center_y = screen_point.y
              
              # 估算SketchUp窗口尺寸
              su_width = view.vpwidth
              su_height = view.vpheight
              
              # 计算SketchUp窗口的左上角
              su_left = su_center_x - (su_width / 2)
              su_top = su_center_y - (su_height / 2)
              
              # 根据SketchUp窗口计算对话框位置（居中）
              left = su_left + (su_width - dialog_width) / 2
              top = su_top + (su_height - dialog_height) / 2
              
              log("获取到SketchUp窗口位置: 左上角(#{su_left.to_i}, #{su_top.to_i}), 宽高(#{su_width}, #{su_height})")
            end
          end
        rescue => e
          log("获取SketchUp窗口位置时出错: #{e.message}", 1)
          # 发生错误时使用默认位置（已设置）
        end
        
        # 确保对话框在屏幕可见区域内
        # 检查左边界
        left = 10 if left < 10
        
        # 检查上边界
        top = 10 if top < 10
        
        # 检查右边界（假设屏幕宽度）
        if left + dialog_width > screen_width - 10
          left = screen_width - dialog_width - 10
        end
        
        # 检查下边界（假设屏幕高度）
        if top + dialog_height > screen_height - 10
          top = screen_height - dialog_height - 10
        end
        
        log("计算的对话框位置: 左上角(#{left.to_i}, #{top.to_i})")
        
        return {
          left: left.to_i,
          top: top.to_i
        }
      rescue => e
        log("计算对话框位置时出错: #{e.message}", 3)
        # 返回安全的默认值
        return {
          left: 200,
          top: 200
        }
      end
    end
    
    # 创建并显示进度对话框
    # @param title [String] 对话框标题
    # @param filename [String] 文件名
    # @param is_upload [Boolean] 是否为上传进度条
    # @return [UI::HtmlDialog, String] 对话框对象和进度ID
    def self.create_progress_dialog(title, filename, is_upload = false)
      begin
        # 生成唯一的session ID和preferences_key
        progress_id = generate_unique_id
        pref_key = is_upload ? "HUB_DirectUploader_#{progress_id}" : "HUB_DirectDownloader_#{progress_id}"
        
        log("创建进度对话框: #{title}, 类型: #{is_upload ? '上传' : '下载'}, ID: #{progress_id}")
        
        # 创建进度文件
        progress_file = create_progress_file(progress_id, is_upload, filename)
        
        # 对话框尺寸
        dialog_width = 550
        dialog_height = 250
        
        # 计算对话框位置
        position = calculate_dialog_position(dialog_width, dialog_height)
        
        # 创建对话框
        dialog = UI::HtmlDialog.new({
          dialog_title: title || (is_upload ? "HUB文件上传" : "HUB文件下载"),
          preferences_key: pref_key,
          scrollable: false,
          resizable: false,
          width: dialog_width,
          height: dialog_height,
          left: position[:left],
          top: position[:top],
          style: UI::HtmlDialog::STYLE_DIALOG
        })
        
        # 获取HTML内容 - 使用内联模板，不读取外部文件
        html_content = is_upload ? 
          get_upload_html_template(filename, progress_id, progress_file) : 
          get_download_html_template(filename, progress_id, progress_file)
        
        # 设置HTML内容
        dialog.set_html(html_content)
        
        # 显示对话框
        dialog.show
        
        # 存储对话框信息到活跃对话框列表
        @active_dialogs[progress_id] = {
          dialog: dialog,
          created_at: Time.now,
          is_upload: is_upload,
          id: progress_id,
          progress: 0,
          progress_file: progress_file,
          completed: false,
          process_id: @process_id
        }
        
        # 清理过期的进度文件（后台进行）
        cleanup_progress_files
        
        log("进度对话框已创建并显示 (ID: #{progress_id})")
        return [dialog, progress_id]
      rescue => e
        log("创建进度对话框出错: #{e.message}", 3)
        log(e.backtrace.join("\n"), 3)
        
        # 降级方案：创建一个简单的消息框通知用户
        message = is_upload ? "正在上传文件，请稍候..." : "正在下载文件，请稍候..."
        UI.messagebox(message, MB_OK)
        
        return [nil, nil]
      end
    end
    
    # 检查对话框是否可用
    # @param dialog [UI::HtmlDialog] 进度对话框
    # @return [Boolean] 对话框是否可用
    def self.dialog_available?(dialog)
      return false unless dialog
      
      begin
        # 尝试调用对话框的方法
        dialog.visible?
        return true
      rescue => e
        log("对话框状态检查失败: #{e.message}", 1)
        return false
      end
    end
    
    # 更新进度条
    # @param dialog [UI::HtmlDialog] 进度对话框
    # @param progress_id [String] 进度ID
    # @param percent [Integer] 完成百分比 (0-100)
    # @param message [String] 状态消息
    # @param file_info [String] 文件信息
    def self.update_progress(dialog, progress_id, percent, message = nil, file_info = nil)
      return unless dialog_available?(dialog) && progress_id
      
      begin
        # 限制百分比在0-100之间
        percent = [0, [percent, 100].min].max
        
        # 准备更新数据
        updates = { progress: percent }
        updates[:status] = message if message
        updates[:file_info] = file_info if file_info
        
        # 更新进度文件
        success = update_progress_file(progress_id, updates)
        
        if success
          log("更新进度条: #{percent}% (进度ID: #{progress_id})")
        else
          log("更新进度条失败: #{percent}% (进度ID: #{progress_id})", 3)
        end
      rescue => e
        log("更新进度条出错: #{e.message}", 3)
      end
    end
    
    # 标记下载完成
    # @param dialog [UI::HtmlDialog] 进度对话框
    # @param progress_id [String] 进度ID
    def self.complete_download(dialog, progress_id)
      return unless dialog_available?(dialog) && progress_id
      
      begin
        # 更新进度文件
        updates = {
          progress: 100,
          status: "下载已完成！准备导入...",
          completed: true
        }
        
        success = update_progress_file(progress_id, updates)
        
        if success
          log("下载已标记为完成 (进度ID: #{progress_id})")
        else
          log("标记下载完成失败 (进度ID: #{progress_id})", 3)
        end
      rescue => e
        log("标记下载完成时出错: #{e.message}", 3)
      end
    end
    
    # 标记上传完成
    # @param dialog [UI::HtmlDialog] 进度对话框
    # @param progress_id [String] 进度ID
    def self.complete_upload(dialog, progress_id)
      return unless dialog_available?(dialog) && progress_id
      
      begin
        # 更新进度文件
        updates = {
          progress: 100,
          status: "上传已完成！准备生成提取码...",
          completed: true
        }
        
        success = update_progress_file(progress_id, updates)
        
        if success
          log("上传已标记为完成 (进度ID: #{progress_id})")
        else
          log("标记上传完成失败 (进度ID: #{progress_id})", 3)
        end
      rescue => e
        log("标记上传完成时出错: #{e.message}", 3)
      end
    end
    
    # 关闭对话框
    # @param dialog [UI::HtmlDialog] 进度对话框
    # @param progress_id [String] 进度ID
    def self.close_dialog(dialog, progress_id)
      return unless dialog_available?(dialog)
      
      begin
        # 删除进度文件
        delete_progress_file(progress_id) if progress_id
        
        # 查找并移除对话框记录
        @active_dialogs.delete(progress_id) if progress_id
        
        dialog.close
        log("进度对话框已关闭 (进度ID: #{progress_id || 'unknown'})")
      rescue => e
        log("关闭进度对话框时出错: #{e.message}", 3)
      end
    end
    
    # 清理所有过期对话框
    def self.cleanup_dialogs
      begin
        now = Time.now
        to_remove = []
        
        @active_dialogs.each do |id, info|
          dialog = info[:dialog]
          created_at = info[:created_at]
          
          # 如果对话框创建超过30分钟，或无法访问，则标记为删除
          if !dialog_available?(dialog) || (now - created_at > 1800)
            to_remove << id
          end
        end
        
        # 移除过期对话框
        to_remove.each do |id|
          # 删除进度文件
          delete_progress_file(id)
          # 从记录中删除
          @active_dialogs.delete(id)
        end
        
        log("清理了 #{to_remove.size} 个过期对话框") if to_remove.size > 0
      rescue => e
        log("清理对话框时出错: #{e.message}", 3)
      end
    end
    
    # 转义HTML特殊字符
    # @param text [String] 要转义的文本
    # @return [String] 转义后的文本
    def self.escape_html(text)
      text.to_s
          .gsub('&', '&amp;')
          .gsub('<', '&lt;')
          .gsub('>', '&gt;')
          .gsub('"', '&quot;')
          .gsub("'", '&#39;')
    end
    
    # 转义JavaScript字符串
    # @param text [String] 要转义的文本
    # @return [String] 转义后的文本
    def self.escape_js(text)
      text.to_s.gsub(/['\\"]/) { |s| "\\#{s}" }
    end
    
  end # module JDT
end # module HUB 